<template>
  <div class="app-container">
    <!-- 添加全局loading遮罩 -->
    <el-loading 
      :visible.sync="fullscreenLoading"
      fullscreen
      element-loading-text="正在处理，请稍候..."
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(0, 0, 0, 0.8)"
    >
    </el-loading>

    <el-card class="query-card">
      <!-- 顶部操作栏 - 使用flex布局自动换行 -->
      <el-form :model="queryParams" size="small" class="query-form">
        <div class="form-left">
          <el-form-item label="数据源" label-width="60px">
            <el-select 
              v-model="queryParams.dataSource" 
              placeholder="请选择" 
              style="width: 100px" 
              @change="handleDataSourceChange" 
              :loading="dsLoading"
            >
              <el-option label="MySQL" value="MASTER" />
              <el-option label="GBase" value="GBASE" />
              <el-option label="DB2" value="SLAVE" />
            </el-select>
          </el-form-item>
          <el-form-item label="库名" label-width="50px">
            <el-select 
              v-model="selectedSchema" 
              placeholder="请选择" 
              style="width: 130px"
              @change="handleSchemaChange"
              :loading="schemaLoading"
            >
              <el-option 
                v-for="item in schemaList"
                :key="item"
                :label="item"
                :value="item"
              />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-input
              v-model="tableSearch"
              placeholder="搜索表名"
              prefix-icon="el-icon-search"
              clearable
              @clear="handleTableSearchClear"
              style="width: 220px"
            />
          </el-form-item>
        </div>
        <div class="form-right">
          <el-button 
            type="primary" 
            icon="el-icon-search" 
            @click="handleQuery"
            :disabled="loading || dsLoading"
          >执行查询</el-button>
          <el-button 
            icon="el-icon-refresh" 
            @click="resetQuery"
            :disabled="loading || dsLoading"
          >重置</el-button>
        </div>
      </el-form>

      <!-- 使用响应式布局 -->
      <el-row :gutter="20" class="content-row">
        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="mb-xs">
          <!-- 表列表 -->
          <el-table
            :data="filteredTables"
            size="small"
            style="width: 100%"
            :height="tableHeight"
            @row-dblclick="handleTableSelect"
            @sort-change="handleSortChange"
          >
            <el-table-column
              prop="schema"
              label="库名/Schema"
              width="130"
            />
            <el-table-column
              prop="tableName"
              label="表名称"
              width="200"
            />
            <el-table-column
              prop="comment"
              label="中文名"
              show-overflow-tooltip
            />
            <el-table-column
              prop="rowCount"
              label="记录数"
              width="100"
              align="right"
              sortable="custom"
            >
              <template slot-scope="scope">
                {{ formatNumber(scope.row.rowCount) }}
              </template>
            </el-table-column>
            <el-table-column
              prop="sizeM"
              label="大小"
              width="100"
              align="right"
              sortable="custom"
            >
              <template slot-scope="scope">
                {{ scope.row.sizeM }}MB
              </template>
            </el-table-column>
          </el-table>
        </el-col>
        
        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
          <!-- SQL编辑器 -->
          <el-form :model="queryParams" size="small">
            <el-form-item label="SQL语句" :label-width="isMobile ? '60px' : '80px'">
              <el-input
                type="textarea"
                v-model="queryParams.sql"
                class="custom-input sql-editor"
              />
            </el-form-item>
          </el-form>
        </el-col>
      </el-row>
    </el-card>

    <!-- 结果表格 -->
    <el-card class="result-card" :body-style="{ padding: '0' }">
      <div slot="header" class="result-header">
        <div class="left">
          <i class="el-icon-data-analysis"></i>
          <span>查询结果</span>
          <el-tag type="success" size="small" effect="plain">{{ total }} 条记录</el-tag>
          <el-button
            type="text"
            icon="el-icon-download"
            @click="handleExport"
            v-if="tableData.length > 0"
          >导出Excel</el-button>
          <el-popover
            placement="bottom"
            width="200"
            trigger="click"
            v-if="tableCols.length > 0"
          >
            <el-checkbox
              :indeterminate="isIndeterminate"
              v-model="checkAll"
              @change="handleCheckAllChange"
            >全选</el-checkbox>
            <el-checkbox-group v-model="selectedCols" @change="handleColChange">
              <div style="max-height: 300px; overflow-y: auto;">
                <el-checkbox
                  v-for="col in tableCols"
                  :key="col"
                  :label="col"
                  style="display: block; margin: 5px 0;"
                >{{ col }}</el-checkbox>
              </div>
            </el-checkbox-group>
            <el-button type="text" slot="reference" icon="el-icon-s-operation">显示列</el-button>
          </el-popover>
        </div>
        <div class="right">
          <pagination
            v-show="total > 0"
            :total="total"
            :page.sync="pageNum"
            :limit.sync="pageSize"
            @pagination="getList"
            :page-sizes="[10, 20, 50, 100, 200, 1000]"
            layout="total, sizes, prev, pager, next"
            small
            :disabled="loading || dsLoading"
            style="display: inline-block; padding: 0"
          />
        </div>
      </div>
      
      <el-table
        ref="dataTable"
        v-loading="loading"
        :data="tableData"
        style="width: 100%"
        height="calc(100vh - 450px)"
        border
        :header-cell-style="headerCellStyle"
        :cell-style="cellStyle"
        :row-class-name="tableRowClassName"
        size="small"
      >
        <el-table-column
          type="index"
          label="序号"
          width="60"
          align="center"
          fixed="left"
          :index="indexMethod"
        />
        <template v-for="(col, index) in visibleCols">
          <el-table-column
            :key="index"
            :prop="col.toLowerCase()"
            :label="col"
            show-overflow-tooltip
            :min-width="calculateWidth(col)"
            align="center"
          >
            <template slot="header" slot-scope="scope">
              <el-tooltip :content="col" placement="top">
                <span class="column-header">{{ col }}</span>
              </el-tooltip>
            </template>
            <template slot-scope="scope">
              <span class="cell-content">{{ scope.row[col] }}</span>
            </template>
          </el-table-column>
        </template>
      </el-table>
    </el-card>
  </div>
</template>

<script>
import { executeSql, getTableList, getSchemaList } from "@/api/tool/sqlquery";
import { saveAs } from 'file-saver';
import * as XLSX from 'xlsx';
import Pagination from "@/components/Pagination";

export default {
  name: "SqlQuery",
  components: { Pagination },
  data() {
    return {
      loading: false,
      queryParams: {
        sql: 'select * from information_schema.TABLES\nwhere 1=1',
        dataSource: 'GBASE'
      },
      tableData: [],
      tableCols: [],
      // 分页参数
      pageNum: 1,
      pageSize: 20,
      total: 0,
      pageSizes: [10, 20, 50, 100, 200, 1000],
      tableSearch: '',
      tableList: [],
      dsLoading: false,
      selectedCols: [],
      checkAll: true,
      isIndeterminate: false,
      schemaList: [],
      selectedSchema: '',
      schemaLoading: false,
      sortBy: '',
      sortOrder: '',
      tableHeight: 300,
      isMobile: false,
      fullscreenLoading: false,  // 添加全屏loading状态
    };
  },
  computed: {
    filteredTables() {
      const search = (this.tableSearch || '').toLowerCase();
      
      if (!Array.isArray(this.tableList)) {
        return [];
      }
      
      let result = this.tableList
        .map(table => {
          if (table && table.TABLENAME) {
            return {
              schema: table.SCHEMA_NAME || 'LOAD',
              tableName: table.TABLENAME.toString(),
              comment: table.TABLE_COMMENT || '-',
              rowCount: Number(table.ROW_COUNT) || 0,
              sizeM: Number(table.SIZE_MB) || 0
            };
          } else if (table && table.tableName) {
            return {
              schema: table.SCHEMA_NAME || 'default',
              tableName: table.tableName.toString(),
              comment: table.TABLE_COMMENT || '-',
              rowCount: Number(table.ROW_COUNT) || 0,
              sizeM: Number(table.SIZE_MB) || 0
            };
          }
          return null;
        })
        .filter(table => {
          if (!table || !table.tableName) return false;
          if (this.selectedSchema && table.schema !== this.selectedSchema) return false;
          return table.tableName.toLowerCase().includes(search);
        });

      // 排序
      if (this.sortBy && this.sortOrder) {
        result.sort((a, b) => {
          const factor = this.sortOrder === 'ascending' ? 1 : -1;
          if (this.sortBy === 'rowCount') {
            return (a.rowCount - b.rowCount) * factor;
          } else if (this.sortBy === 'sizeM') {
            return (a.sizeM - b.sizeM) * factor;
          }
          return 0;
        });
      }

      return result;
    },
    visibleCols() {
      // 确保返回的是原始列名
      return this.selectedCols;
    }
  },
  created() {
    // 组件创建时加载GBase数据
    this.handleDataSourceChange('GBASE');
  },
  mounted() {
    this.checkDevice();
    window.addEventListener('resize', this.handleResize);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize);
  },
  methods: {
    handleQuery() {
      this.pageNum = 1;
      this.getList();
    },
    async getList() {
      if (!this.queryParams.sql) {
        this.$message.warning("请输入SQL语句");
        return;
      }
      if (this.loading) return;
      
      this.loading = true;
      this.fullscreenLoading = true;
      
      try {
        const response = await executeSql(
          this.queryParams.sql,
          this.queryParams.dataSource,
          this.pageNum,
          this.pageSize
        );
        
        // 先更新列信息
        if (response.rows && response.rows.length > 0) {
          this.tableCols = Object.keys(response.rows[0]);
          this.selectedCols = [...this.tableCols];
          this.checkAll = true;
          this.isIndeterminate = false;
        }
        
        // 等待DOM更新
        await this.$nextTick();
        
        // 再更新数据
        this.tableData = response.rows;
        this.total = response.total;
        
        // 强制重新渲染表格
        if (this.$refs.dataTable) {
          this.$refs.dataTable.doLayout();
        }
      } catch (error) {
        this.$message.error('查询失败: ' + error.message);
      } finally {
        this.loading = false;
        this.fullscreenLoading = false;
      }
    },
    resetQuery() {
      this.queryParams = {
        sql: 'select * from information_schema.TABLES\nwhere 1=1',
        dataSource: 'GBASE'
      };
      this.pageNum = 1;
      this.getList();
    },
    handleExport() {
      // 创建工作簿
      const wb = XLSX.utils.book_new();
      
      // 转换数据为工作表
      const ws = XLSX.utils.json_to_sheet(this.tableData);
      
      // 将工作表添加到工作簿
      XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
      
      // 生成excel文件
      const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
      
      // 保存文件
      const blob = new Blob([wbout], { type: 'application/octet-stream' });
      saveAs(blob, 'sql_result.xlsx');
    },
    tableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2 === 1) {
        return 'stripe-row';
      }
      return '';
    },
    headerCellStyle() {
      return {
        backgroundColor: '#f8f9fb',
        color: '#606266',
        fontWeight: 'bold',
        borderBottom: '2px solid #EBEEF5'
      }
    },
    cellStyle() {
      return {
        fontSize: '13px',
        padding: '8px 0'
      }
    },
    indexMethod(index) {
      return (this.pageNum - 1) * this.pageSize + index + 1
    },
    calculateWidth(column) {
      // 获取该列所有数据
      const values = this.tableData.map(row => row[column]?.toString() || '');
      // 加入列名
      values.push(column);
      
      // 计算最大长度
      const maxLength = Math.max(...values.map(v => v.length));
      
      // 根据内容类型调整宽度
      if (this.isNumberColumn(values)) {
        // 数字列
        return Math.max(80, maxLength * 10);
      } else if (this.isDateColumn(column)) {
        // 日期列
        return 150;
      } else {
        // 普通文本列
        return Math.max(100, Math.min(300, maxLength * 12));
      }
    },
    isNumberColumn(values) {
      return values.every(v => !isNaN(v) && v !== '');
    },
    isDateColumn(column) {
      return column.toLowerCase().includes('date') || 
             column.toLowerCase().includes('time') ||
             column.toLowerCase().includes('_dt') ||
             column.toLowerCase().includes('_tm');
    },
    // 数据源变化时获取表列表
    async handleDataSourceChange(value) {
      this.dsLoading = true;
      this.fullscreenLoading = true;  // 显示全屏loading
      this.tableList = [];
      this.selectedSchema = '';
      this.schemaList = [];
      
      try {
        await this.getSchemaList(value);
        const res = await getTableList(value);
        if (res.code === 200) {
          this.tableList = res.data;
        }
      } catch (error) {
        this.$message.error('获取表列表失败: ' + error.message);
      } finally {
        this.dsLoading = false;
        this.fullscreenLoading = false;  // 隐藏全屏loading
      }
    },
    // 获取库/schema列表
    async getSchemaList(dataSource) {
      this.schemaLoading = true;
      try {
        const res = await getSchemaList(dataSource);  // 需要添加后端接口
        if (res.code === 200) {
          this.schemaList = res.data || [];
          if (this.schemaList.length > 0) {
            this.selectedSchema = dataSource === 'SLAVE' ? 'LOAD' : this.schemaList[0];
          }
        }
      } catch (error) {
        this.$message.error('获取库列表失败: ' + error.message);
      } finally {
        this.schemaLoading = false;
      }
    },
    handleSchemaChange(value) {
      if (this.loading || this.dsLoading) return;  // 如果正在加载则不处理
      this.selectedSchema = value;
    },
    handleTableSelect(row) {
      if (this.loading || this.dsLoading) return;  // 如果正在加载则不处理
      const schema = row.schema ? `${row.schema}.` : '';
      this.queryParams.sql = `select * from ${schema}${row.tableName}\nwhere 1=1`;
    },
    // 清除表搜索
    handleTableSearchClear() {
      this.tableSearch = '';
    },
    handleCheckAllChange(val) {
      this.selectedCols = val ? [...this.tableCols] : [];
      this.isIndeterminate = false;
    },
    handleColChange(value) {
      this.selectedCols = value;
      const checkedCount = value.length;
      this.checkAll = checkedCount === this.tableCols.length;
      this.isIndeterminate = checkedCount > 0 && checkedCount < this.tableCols.length;
      
      // 强制更新表格
      this.$nextTick(() => {
        this.$refs.dataTable && this.$refs.dataTable.doLayout();
      });
    },
    formatNumber(num) {
      if (!num) return '0';
      return new Intl.NumberFormat().format(num);
    },
    handleSortChange({ prop, order }) {
      this.sortBy = prop;
      this.sortOrder = order;
    },
    checkDevice() {
      this.isMobile = window.innerWidth < 768;
      this.adjustHeight();
    },
    handleResize() {
      this.checkDevice();
    },
    adjustHeight() {
      if (this.isMobile) {
        this.tableHeight = 200;
      } else {
        this.tableHeight = 300;
      }
    },
    handlePaginationChange(val) {
      this.pageNum = val.page;
      this.pageSize = val.limit;
      this.getList();
    }
  },
  // 添加watch来监控变化
  watch: {
    tableData: {
      immediate: true,
      handler(newData) {
        if (newData && newData.length > 0) {
          const newCols = Object.keys(newData[0]);
          if (JSON.stringify(this.tableCols) !== JSON.stringify(newCols)) {
            this.tableCols = newCols;
            this.selectedCols = [...newCols];
            this.checkAll = true;
            this.isIndeterminate = false;
            
            // 强制重新渲染表格
            this.$nextTick(() => {
              if (this.$refs.dataTable) {
                this.$refs.dataTable.doLayout();
              }
            });
          }
        }
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.app-container {
  padding: 20px;
  background-color: #f0f2f5;
  
  .query-card, .result-card {
    border-radius: 4px;
    box-shadow: 0 2px 12px 0 rgba(0,0,0,.05);
    
    &:hover {
      box-shadow: 0 4px 16px 0 rgba(0,0,0,.1);
    }
  }
  
  .result-card {
    margin-top: 20px;
    display: flex;
    flex-direction: column;
    min-height: calc(100vh - 300px);
    
    .result-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 15px 20px;
      border-bottom: 1px solid #ebeef5;
      
      .left {
        display: flex;
        align-items: center;
        gap: 15px;
        
        i {
          font-size: 20px;
          color: #409EFF;
        }
        
        span {
          font-size: 16px;
          font-weight: 500;
        }
        
        .el-button {
          padding: 0;
          font-size: 14px;
        }
      }
      
      .right {
        display: flex;
        align-items: center;
        gap: 10px;
        
        ::v-deep .pagination-container {
          padding: 0;
          margin: 0;
          background: transparent;
          border: none;
          
          .el-pagination {
            padding: 0;
            margin: 0;
            font-size: 13px;
            
            .el-pagination__sizes {
              margin: 0 10px;
            }
          }
        }
      }
    }
  }
  
  .custom-input {
    ::v-deep .el-textarea__inner {
      font-family: 'Consolas', monospace;
      font-size: 14px;
      line-height: 1.5;
      padding: 12px;
      border-radius: 4px;
      
      &:focus {
        border-color: #409EFF;
        box-shadow: 0 0 0 2px rgba(64,158,255,.2);
      }
    }
  }
  
  .el-table {
    ::v-deep {
      .stripe-row {
        background-color: #fafafa;
        &:hover > td {
          background-color: #f0f7ff !important;
        }
      }
      
      .column-header {
        font-weight: bold;
      }
      
      .cell-content {
        color: #606266;
      }
      
      th.is-leaf {
        border-bottom: 2px solid #EBEEF5;
      }
      
      td {
        transition: background-color .3s;
      }
      
      .el-table__column-resize-proxy {
        transition: left 0.3s;
      }
      
      .cell {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }
  }
  
  .pagination-container {
    padding: 15px 20px;
    background: #fff;
    border-top: 1px solid #ebeef5;
    position: sticky;
    bottom: 0;
    z-index: 10;
    margin-top: auto;
  }
  
  .table-list-card {
    margin-top: 0;
    height: 340px;
    
    .loading-container {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;
      padding: 20px;
      
      i {
        font-size: 24px;
        color: #409EFF;
      }
      
      span {
        margin-top: 10px;
        color: #909399;
      }
    }
    
    .el-scrollbar {
      height: calc(100% - 40px);
      position: relative;
    }
    
    .table-list-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 10px;
      
      .table-count {
        color: #909399;
        font-size: 12px;
      }
    }
    
    .el-table {
      ::v-deep {
        .el-table__row {
          cursor: pointer;
          &:hover > td {
            background-color: #f5f7fa;
          }
        }
      }
    }
  }
}

.result-header {
  .left {
    .el-button + .el-button {
      margin-left: 10px;
    }
  }
}

::v-deep .el-checkbox {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.table-list-card {
  .el-table {
    ::v-deep {
      .ascending .sort-caret.ascending {
        border-bottom-color: #409EFF;
      }
      .descending .sort-caret.descending {
        border-top-color: #409EFF;
      }
      .el-table__column-filter-trigger {
        line-height: 24px;
      }
      .el-tooltip {
        cursor: help;
      }
    }
  }
}

.query-card {
  .el-form {
    margin-bottom: 15px;
    
    .el-form-item {
      margin-bottom: 0;
      margin-right: 10px;
    }
  }
}

.sql-editor {
  ::v-deep .el-textarea__inner {
    height: 300px !important;
    resize: none;
  }
}

.query-form {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 10px;
  
  .form-left {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    
    @media screen and (max-width: 768px) {
      width: 100%;
      
      .el-form-item {
        margin-right: 0;
        width: 100%;
        
        .el-select,
        .el-input {
          width: 100% !important;
        }
      }
    }
  }
  
  .form-right {
    @media screen and (max-width: 768px) {
      width: 100%;
      display: flex;
      justify-content: space-between;
      
      .el-button {
        flex: 1;
        margin-left: 10px;
        
        &:first-child {
          margin-left: 0;
        }
      }
    }
  }
}

.content-row {
  @media screen and (max-width: 768px) {
    .mb-xs {
      margin-bottom: 15px;
    }
  }
}

.sql-editor {
  ::v-deep .el-textarea__inner {
    @media screen and (max-width: 768px) {
      height: 200px !important;
    }
  }
}

// 添加loading样式
::v-deep .el-loading-mask {
  .el-loading-text {
    color: #fff;
    font-size: 14px;
    margin-top: 10px;
  }
  .el-icon-loading {
    font-size: 30px;
    color: #fff;
  }
}

::v-deep .el-pagination {
  &.is-disabled {
    .btn-prev,
    .btn-next,
    .el-pager li,
    .el-select .el-input {
      cursor: not-allowed;
      
      &:hover {
        color: #c0c4cc;
      }
    }
    
    .el-select .el-input.is-disabled .el-input__inner {
      background-color: #f5f7fa;
      border-color: #e4e7ed;
      color: #c0c4cc;
      cursor: not-allowed;
    }
  }
}
</style> 